/*
 * Ascenseur.java
 *
 * Created on 7 janvier 2004, 21:48
 */

package projet_ascenseur;

import controle.Controle;
import requetes.Deplacement;

/*
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Frame;
*/
/**
 * @author oui
 */

public class Ascenseur extends java.util.TimerTask {

	/** Le nombre d'etages total */
	int nombre_etages;

	/** nombre de pas entre chaque etages */
	int hauteur_etage;

	/** delais de changement de pas en ms */
	long delai_pas;

	/**
	 * Temps d'arret a un etage apres l'ouverture de la porte (en nombre de pas)
	 */
	int delai_arret_cabine;

	/** position: qui contient le sens et l'etage courant en pas d'etage */
	Deplacement position;

	/** l'ascenseur s'arretera au prochain etage */
	boolean arret_prochain;

	/** la porte est fermee quand delai_avant_fermeture_porte == 0 !!! */
	int delai_avant_fermeture_porte;
	
	/** temps em ms pour que la porte s'ouvre ou se ferme completement */
	int duree_ouverture_fermeture_porte;
	
	/** la porte est completement fermee qd delai_fermeture_porte = 0 */
	int delai_fermeture_porte;
	
	/** la porte est completement fermee qd delai_ouverture_porte = duree_ouverture_fermeture_porte */
	int delai_ouverture_porte;
	
	/** Si on est dans un arret d'urgence */
	boolean urgence;

	/** objet Thread qui va appeler regulierement notre methode run() */
	java.util.Timer timer;

	Controle ordonnanceur;

	/** Composants de la fenetre de test */
	java.awt.Frame fenetre;

	java.awt.Button bt_etat;

	java.awt.Button bt_porteGauche;

	java.awt.Button bt_porteDroite;

	java.awt.Checkbox boite_arret;

	/**
	 * Cree un nouvel objet Ascenseur la hauteur_etage et le_delais_arret_cabine
	 * sont en nombre de pas
	 * @param nb_etages		nombres d'etages
	 * @param le_delai_pas			deplacement de l'ascenseur en une seconde
	 * @param Hauteur_etage		hauteur d'un etage
	 * @param le_delai_arret_cabine			duree d'un arret a un etage
	 * @param duree_ouverture_fermeture_porte	temps mis par les portes pour completement s'ouvrir( ou se fermer )
	 */
	public Ascenseur(int nb_etages, long le_delai_pas, int Hauteur_etage,
			 int le_delai_arret_cabine, int duree_ouverture_fermeture_porte) {

		nombre_etages = nb_etages;
		hauteur_etage = Hauteur_etage;
		position = new Deplacement(Deplacement.INDEFINI, 0);
		delai_pas = le_delai_pas;
		delai_arret_cabine = le_delai_arret_cabine;
		
		
		delai_fermeture_porte = 0;
		delai_ouverture_porte = this.duree_ouverture_fermeture_porte = duree_ouverture_fermeture_porte;
		
		arret_prochain = urgence = false;

		/** demarrage du compteur */
		timer = new java.util.Timer();
		timer.schedule(this, 0, delai_pas);
	}

	
	public void assigne_ordonnanceur(Controle ordo) {
		ordonnanceur = ordo;
	}

	public void monter() {
		// assert delai_avant_fermeture_porte == 0;
		position.sens_montee();
		ordonnanceur.setSens( Deplacement.MONTEE );
	}

	public void descendre() {
		// assert delai_avant_fermeture_porte == 0;
		position.sens_descente();
		ordonnanceur.setSens( Deplacement.DESCENTE );
	}
	
	
	/**
	 * Cette Methode met fin a l 'arret d'urgence
	 */
	public synchronized void finArretUrgence()
	{
		urgence = false;
		notify();
		//si les portes sont fermees on previent le centre de controle
		if( delai_fermeture_porte == 0)
		{
			ordonnanceur.signal_porte_fermee();
		}
	}

	
	/**
	* Cette Methode met l'ascenseur en arret d'urgence
	*/
	public synchronized void arreter() {
		position.sens_indefini();
		ordonnanceur.setSens( Deplacement.INDEFINI );
		arret_prochain = false;
		System.err.println("Arret d'urgence !!");
		try 
		{
			urgence = true;
			this.wait();			
		} catch (InterruptedException ex) {
		}

	}

	public void arreter_prochain_niveau() {
		arret_prochain = true;
	}

	public void ouverture_porte() {
		// assert position.est_arrete();
		java.awt.Toolkit.getDefaultToolkit().beep();
		
		delai_avant_fermeture_porte = delai_arret_cabine;
		
		//Si l'action d'ouverture est terminee
		if( delai_ouverture_porte == duree_ouverture_fermeture_porte )
		{
			//l'action de fermeture est terminee
			if( delai_fermeture_porte == 0 )
			{
				//On entame la procedure entiere
				delai_ouverture_porte = 0;
				delai_fermeture_porte = -1;
			}
			//sinon on inverse l'action
			else
			{
				delai_ouverture_porte = delai_fermeture_porte;
				delai_fermeture_porte = -1;
			}
		}
	}

	public void run() {


		//en cas d'urgence on verrouille les portes
		if( !urgence && delai_ouverture_porte < duree_ouverture_fermeture_porte )
		{
			delai_ouverture_porte++;
			ordonnanceur.setOuverture(delai_ouverture_porte,duree_ouverture_fermeture_porte);
			if( delai_ouverture_porte == duree_ouverture_fermeture_porte )
			{
				System.err.println("Porte Ouverte");
				delai_fermeture_porte = duree_ouverture_fermeture_porte;
			}
		}
		//encas durgence on verrouille les portes
		if( !urgence && delai_fermeture_porte > 0 )
		{
			delai_fermeture_porte--;
			ordonnanceur.setOuverture(delai_fermeture_porte,duree_ouverture_fermeture_porte);
			if( delai_fermeture_porte == 0 )
			{
				System.err.println("Porte Fermee");
				ordonnanceur.signal_porte_fermee();
			}
		}
		
		
		if (!position.est_arrete()) {
			position.change_etage(); // incremente ou decremente le pas
										// d'etage

			if (position.etage % hauteur_etage == 0) {
				if (arret_prochain) {
					position.sens_indefini();
					arret_prochain = false;
					ouverture_porte();
					System.err.println("OUVERTURE PORTE");
				}
				ordonnanceur.signaler_etage();
			}
		}else
			ordonnanceur.setSens( Deplacement.INDEFINI );
	}
}
